`define  VERBOSE_WB  0           // All activity on the WISHBONE is recorded
`define  VERBOSE_LINE_STATUS 0   // Details about the lsr (line status register)
`define  FAST_TEST   1           // 64/1024 packets are sent
`define  LITLE_ENDIAN 1

module uart_cpld(
input            uart_clk         ,
input            uart_rst_n       ,
input [4:0]      uart_slave_addr  ,
input            uart_slave_write ,
input            uart_slave_read  ,
input [7:0]      uart_slave_wrdata,
output reg [8:0] uart_slave_rddata,
input            luart_sol_sw,
input [7:0]      clk_divisor,
input [7:0]      receiver_wdata    ,
output           rfifo_full       ,
input            receiver_wen       ,
input            remote_rfifo_full        ,
output           uart_tx_o        ,
input            uart_rx_i        ,
output            transmitter_rden       ,

input            cts_pad_i        , 
                 dsr_pad_i        , 
                 ri_pad_i         , 
                 dcd_pad_i        ,
output           rts_pad_o        ,
output           dtr_pad_o        ,
output [7:0]     transmitter_data_out   ,
output           tfifo_empty      ,
output           reg int_o            
`ifdef UART_HAS_BAUDRATE_OUTPUT
,output    baud_o
`endif
);

reg                                         enable;
`ifdef UART_HAS_BAUDRATE_OUTPUT
assign baud_o = enable; // baud_o is actually the enable signal
`endif


parameter UART_ADDR_WIDTH=5;
parameter UART_DATA_WIDTH=32;

// Register addresses
parameter REG_ADDR_RB    =5'd0;    // receiver buffer
parameter REG_ADDR_TR    =5'd0;    // transmitter
parameter REG_ADDR_IE    =5'd1;    // Interrupt enable
parameter REG_ADDR_II    =5'd2;    // Interrupt identification
parameter REG_ADDR_FC    =5'd2;    // FIFO control
parameter REG_ADDR_LC    =5'd3;    // Line Control
parameter REG_ADDR_MC    =5'd4;    // Modem control
parameter REG_ADDR_LS    =5'd5;    // Line status
parameter REG_ADDR_MS    =5'd6;    // Modem status
parameter REG_ADDR_SR    =5'd7;    // Scratch register
parameter REG_ADDR_DL1   =5'd0;    // Divisor latch bytes (1-2)
parameter REG_ADDR_DL2   =5'd1;

// Interrupt Enable register bits
parameter UART_IE_RDA   =0;    // Received Data available interrupt
parameter UART_IE_THRE   =1;    // Transmitter Holding Register empty interrupt
parameter UART_IE_RLS   =2;    // Receiver Line Status Interrupt
parameter UART_IE_MS   =3;    // Modem Status Interrupt

// Interrupt Identification register bits
parameter UART_II_IP   =0;    // Interrupt pending when 0
//parameter UART_II_II   =3:1    // Interrupt identification

// Interrupt identification values for bits=3;:1
parameter UART_II_RLS   =3'b011;    // Receiver Line Status
parameter UART_II_RDA   =3'b010;    // Receiver Data available
parameter UART_II_TI    =3'b110;    // Timeout Indication
parameter UART_II_THRE  =3'b001;    // Transmitter Holding Register empty
parameter UART_II_MS    =3'b000;    // Modem Status

// FIFO Control Register bits
//parameter UART_FC_TL   =1:0    // Trigger level

// FIFO trigger level values
//parameter UART_FC_1       =2'b00
//parameter UART_FC_4       =2'b01
//parameter UART_FC_8       =2'b10
//parameter UART_FC_14      =2'b11

// Line Control register bits
//parameter UART_LC_BITS   =1:0    // bits in character
parameter UART_LC_SB   =2;    // stop bits
parameter UART_LC_PE   =3;    // parity enable
parameter UART_LC_EP   =4;    // even parity
parameter UART_LC_SP   =5;    // stick parity
parameter UART_LC_BC   =6;    // Break control
parameter UART_LC_DL   =7;    // Divisor Latch access bit

// Modem Control register bits
parameter UART_MC_DTR   =0;
parameter UART_MC_RTS   =1;
parameter UART_MC_OUT1   =2;
parameter UART_MC_OUT2   =3;
parameter UART_MC_LB   =4;    // Loopback mode

// Line Status Register bits
parameter UART_LS_DR   =0;    // Data ready
parameter UART_LS_OE   =1;    // Overrun Error
parameter UART_LS_PE   =2;    // Parity Error
parameter UART_LS_FE   =3;    // Framing Error
parameter UART_LS_BI   =4;    // Break interrupt
parameter UART_LS_TFE   =5;    // Transmit FIFO is empty
parameter UART_LS_TE   =6;    // Transmitter Empty indicator
parameter UART_LS_EI   =7;    // Error indicator

// Modem Status Register bits
parameter UART_MS_DCTS   =0;    // Delta signals
parameter UART_MS_DDSR   =1;
parameter UART_MS_TERI   =2;
parameter UART_MS_DDCD   =3;
parameter UART_MS_CCTS   =4;    // Complement signals
parameter UART_MS_CDSR   =5;
parameter UART_MS_CRI   =6;
parameter UART_MS_CDCD   =7;

// FIFO parameter defines

parameter UART_FIFO_WIDTH   =8;
parameter UART_FIFO_DEPTH   =16;
parameter UART_FIFO_POINTER_W   =4;
parameter UART_FIFO_COUNTER_W   =5;
// receiver fifo has width=11; because it has break, parity and framing error bits
parameter UART_FIFO_REC_WIDTH =11;





reg [3:0]                                 ier;
reg [3:0]                                 iir;
reg [1:0]                                 fcr;  /// bits 7 and 6 of fcr. Other bits are ignored
reg [4:0]                                 mcr;
reg [7:0]                                 lcr;
reg [7:0]                                 msr;
reg [15:0]                                 dl;  // 32-bit divisor latch
reg [7:0]                                 scratch; // UART scratch register
reg                                         start_dlc; // activate dlc on writing to UART_DL1
reg                                         lsr_read_clr_d; // delay for lsr_read_rise condition
reg                                         msi_reset; // reset MSR 4 lower bits indicator
//reg                                         threi_clear; // THRE interrupt clear flag
reg [15:0]                                 dlc;  // 32-bit divisor latch counter

reg [3:0]                                 trigger_level; // trigger level of the receiver FIFO
reg                                         rx_reset;
reg                                         tx_reset;

wire                                         dlab;               // divisor latch access bit
wire                                         loopback;           // loopback bit (MCR bit 4)
wire                                         cts, dsr, ri, dcd;       // effective signals
wire                    cts_c, dsr_c, ri_c, dcd_c; // Complement effective signals (considering loopback)

// LSR bits wires and regs
wire [7:0]                                 lsr;
wire                                         lsr0, lsr1, lsr2, lsr3, lsr4, lsr5, lsr6, lsr7;
reg                                        lsr0r, lsr1r, lsr2r, lsr3r, lsr4r, lsr5r, lsr6r, lsr7r;
wire                                         lsr_read_rise; // lsr_read_rise

//
// ASSINGS
//

assign                                     lsr[7:0] = { lsr7r, lsr6r, lsr5r, lsr4r, lsr3r, lsr2r, lsr1r, lsr0r };

assign                                     {cts, dsr, ri, dcd} = ~{cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i};

assign                  {cts_c, dsr_c, ri_c, dcd_c} = loopback ? {mcr[UART_MC_RTS],mcr[UART_MC_DTR],mcr[UART_MC_OUT1],mcr[UART_MC_OUT2]}
                                                               : {cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i};

assign                                     dlab = lcr[UART_LC_DL];
assign                                     loopback = mcr[4];

// assign modem outputs
assign                                     rts_pad_o = mcr[UART_MC_RTS];
assign                                     dtr_pad_o = mcr[UART_MC_DTR];

// Interrupt signals
wire                                         rls_int;  // receiver line status interrupt
wire                                         rda_int;  // receiver data available interrupt
wire                                         ti_int;   // timeout indicator interrupt
wire                                        thre_int; // transmitter holding register empty interrupt
wire                                         ms_int;   // modem status interrupt

// FIFO signals
reg                                         tfifo_wren;
reg                                         rfifo_rden;
//wire [UART_FIFO_REC_WIDTH-1:0]     rf_data_out;
wire [11-1:0]     rf_data_out;
wire                                         rx_fifo_wen; // an error (parity or framing) is inside the fifo
wire [UART_FIFO_COUNTER_W-1:0]     rf_count;
wire [UART_FIFO_COUNTER_W-1:0]     tf_count;
wire [2:0]                                 tstate;
wire [3:0]                                 rstate;
wire [9:0]                                 counter_t;

wire                      thre_set_en; // THRE status is delayed one character time when a character is written to fifo.
reg  [7:0]                block_cnt;   // While counter counts, THRE status is blocked (delayed one character cycle)
reg  [7:0]                block_value; // One character length minus stop bit

// Transmitter Instance
wire serial_out;
reg [7:0] 			tfifo_wrdata_in;
wire tfifo_full;
wire clk = uart_clk;
wire rst_n = uart_rst_n;
cpld_uart_transmitter transmitter(
   .clk              (clk          ),
   .rst_n            (rst_n        ), 
   .uart_clk         (uart_clk     ),
   .uart_rst_n       (uart_rst_n   ),
   .luart_sol_sw     (luart_sol_sw),
   .lcr              (lcr          ), 
   .tfifo_wren       (tfifo_wren   ), 
   .tfifo_wrdata_in  (tfifo_wrdata_in), 
   .enable           (enable       ), 
   .serial_out       (serial_out   ), 
   .transmitter_data_out  (transmitter_data_out),
   .tstate           (tstate       ), 
   //.tf_count         (tf_count     ), 
   .tx_reset         (tx_reset     ),
   .transmitter_rden       (transmitter_rden   ),
   .remote_rfifo_full(remote_rfifo_full),
   .tfifo_full      (tfifo_full  ),
   .tfifo_empty      (tfifo_empty  ),

   .lsr_read_rise    (lsr_read_rise)
);

//reg [63:0] tfifo_we_cnt;
//always @(posedge clk or negedge rst_n) begin
//    if(!rst_n) tfifo_we_cnt <=0;
//    else if(tfifo_wren)
//       tfifo_we_cnt <= tfifo_we_cnt +1;
//end
//
//reg [63:0] tfifo_re_cnt;
//always @(posedge hclk or negedge hresetn) begin
//    if(!hresetn) tfifo_re_cnt <=0;
//    else if(transmitter_rden)
//       tfifo_re_cnt <= tfifo_re_cnt +1;
//end

reg uart_rx_ff1,uart_rx_ff2;
always @(posedge clk or negedge rst_n) begin
   if(!rst_n) begin
      uart_rx_ff1 <=1;
      uart_rx_ff2 <=1;
   end
   else begin
      uart_rx_ff1 <= uart_rx_i;
      uart_rx_ff2 <= uart_rx_ff1;
   end
end


// handle loopback
wire serial_in = loopback ? serial_out : uart_rx_ff2;
assign uart_tx_o = loopback ? 1'b1 : serial_out;

wire rfifo_empty;
wire rf_overrun;
// Receiver Instance
cpld_uart_receiver receiver(
   .clk           (clk          ),
   .rst_n         (rst_n       ), 
   .luart_sol_sw     (luart_sol_sw),
   .lcr            (lcr          ), 
   .rfifo_rden     (rfifo_rden   ), 
   .serial_in      (serial_in    ),
   .receiver_wdata     (receiver_wdata),
   .rfifo_full(rfifo_full   ),
   .rfifo_empty    (rfifo_empty   ),
   .receiver_wen     (receiver_wen   ),
   .enable         (enable       ), 
   .counter_t      (counter_t    ), 
   .rf_count       (rf_count     ), 
   .rf_data_out    (rf_data_out  ), 
   .rx_fifo_wen   (rx_fifo_wen ),
   .error_bit     (error_bit),
   .rf_overrun     (rf_overrun   ), 
   .rx_reset       (rx_reset     ), 
   .lsr_read_rise  (lsr_read_rise), 
   .rstate         (rstate       )//, 
  // .rfifo_wen_pulse  (rfifo_wen_pulse)
);

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) uart_slave_rddata <=9'b0;
    else case (uart_slave_addr)
        REG_ADDR_RB   :  uart_slave_rddata <= dlab ? {1'b0,dl[7:0]} : {rfifo_empty,rf_data_out[7:0]};
        REG_ADDR_IE    : begin
             uart_slave_rddata[7:0] <= dlab ? dl[15:8] : ier;
             uart_slave_rddata[8] <=0;
        end
        REG_ADDR_II    : begin
           uart_slave_rddata[7:0] <= {4'b1100,iir};
           uart_slave_rddata[8] <=0;
        end
        REG_ADDR_LC    : begin
           uart_slave_rddata[7:0] <= lcr;
           uart_slave_rddata[8] <=0;
        end
        REG_ADDR_LS    : begin
           uart_slave_rddata[7:0] <= lsr;
           uart_slave_rddata[8] <=0;
        end
        REG_ADDR_MS    : begin
           uart_slave_rddata[7:0] <= msr;
           uart_slave_rddata[8] <=0;
        end
        REG_ADDR_SR    : begin
           uart_slave_rddata[7:0] <= scratch;
           uart_slave_rddata[8] <=0;
        end
        default:  uart_slave_rddata <= 9'b0; // ??
    endcase // case(uart_slave_addr)
end // always @ (dl or dlab or ier or iir or scratch...


always @(*)begin//(posedge clk or negedge rst_n)
   //if(!rst_n)
   //    rfifo_rden <=  0; 
   //else
   //if (rfifo_rden)    // restore the signal to 0 after one clock cycle
   //    rfifo_rden <=  0;
   //else
   //if (uart_slave_read && uart_slave_addr == REG_ADDR_RB && !dlab)
   //    rfifo_rden <=  1; // advance read pointer
   rfifo_rden = (uart_slave_read && uart_slave_addr == REG_ADDR_RB && !dlab) ;
end

wire lsr_read_clr;
wire     iir_read;
wire  msr_read;
wire    fifo_read;
wire    fifo_write;

assign lsr_read_clr = (uart_slave_read && uart_slave_addr == REG_ADDR_LS && !dlab);
assign iir_read = (uart_slave_read && uart_slave_addr == REG_ADDR_II && !dlab);
assign msr_read = (uart_slave_read && uart_slave_addr == REG_ADDR_MS && !dlab);
assign fifo_read = (uart_slave_read && uart_slave_addr == REG_ADDR_RB && !dlab);
assign fifo_write = (uart_slave_write && uart_slave_addr == REG_ADDR_TR && !dlab);

// lsr_read_clr_d delayed signal handling
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        lsr_read_clr_d <=  0;
    else // reset bits in the Line Status Register
        lsr_read_clr_d <=  lsr_read_clr;
end

// lsr_read_rise is rise detected
assign lsr_read_rise = lsr_read_clr && ~lsr_read_clr_d;

// msi_reset signal handling
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        msi_reset <=  1;
    else
    if (msi_reset)
        msi_reset <=  0;
    else
    if (msr_read)
        msi_reset <=  1; // reset bits in Modem Status Register
end


//
//   WRITES AND RESETS   //
//
// Line Control Register
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        lcr <=  8'b00000011; // 8n1 setting
    else
    if (uart_slave_write && uart_slave_addr==REG_ADDR_LC)
        lcr <=  uart_slave_wrdata;

// Interrupt Enable Register or UART_DL
always @(posedge clk or negedge rst_n)
    if(!rst_n)
    begin
        ier <=  4'b0000; // no interrupts after reset
        dl[15:8] <=  8'b0;
    end
    else if (uart_slave_write && uart_slave_addr==REG_ADDR_IE)
        if (dlab) begin
            dl[15:8] <=  uart_slave_wrdata;
        end
        else
            ier <=  uart_slave_wrdata[3:0]; 


// FIFO Control Register and rx_reset, tx_reset signals
always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        fcr <=  2'b11; 
        rx_reset <=  0;
        tx_reset <=  0;
    end else
    if (uart_slave_write && uart_slave_addr==REG_ADDR_FC) begin
        fcr <=  uart_slave_wrdata[7:6];
        rx_reset <=  uart_slave_wrdata[1];
        tx_reset <=  uart_slave_wrdata[2];
    end else begin
        rx_reset <=  0;
        tx_reset <=  0;
    end

// Modem Control Register
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        mcr <=  5'b0; 
    else
    if (uart_slave_write && uart_slave_addr==REG_ADDR_MC)
            mcr <=  uart_slave_wrdata[4:0];

// Scratch register no use
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        scratch <=  0;  
    else
    if (uart_slave_write && uart_slave_addr==REG_ADDR_SR)
        scratch <=  uart_slave_wrdata;

// TX_FIFO or UART_DL1
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dl[7:0]  <=  8'h01;
        tfifo_wren   <=  1'b0;
        start_dlc <=  1'b0;
        tfifo_wrdata_in <=0;
    end
    else
    if (uart_slave_write && uart_slave_addr==REG_ADDR_TR)
        if (dlab) begin
            dl[7:0] <=  uart_slave_wrdata;
            start_dlc <=  1'b1; // enable DL counter
            tfifo_wren <=  1'b0;
        end
        else begin
            tfifo_wren   <=  1'b1;
            tfifo_wrdata_in <= uart_slave_wrdata;
            start_dlc <=  1'b0;
        end // else: !if(dlab)
    else begin
        start_dlc <=  1'b0;
        tfifo_wren   <=  1'b0;
    end // else: !if(dlab)
end

// Receiver FIFO trigger level selection logic (asynchronous mux)
always @(fcr)
    case (fcr[1:0])
        2'b00 : trigger_level = 1;
        2'b01 : trigger_level = 4;
        2'b10 : trigger_level = 8;
        2'b11 : trigger_level = 14;
    endcase // case(fcr[UART_FC_TL])
    
//
//  STATUS REGISTERS  //
//

// Modem Status Register
reg [3:0] delayed_modem_signals;
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
      begin
          msr <=  0;
          delayed_modem_signals[3:0] <=  0;
      end
    else begin
        msr[UART_MS_DDCD:UART_MS_DCTS] <=  msi_reset ? 4'b0 :
            msr[UART_MS_DDCD:UART_MS_DCTS] | ({dcd, ri, dsr, cts} ^ delayed_modem_signals[3:0]);
        msr[UART_MS_CDCD:UART_MS_CCTS] <=  {dcd_c, ri_c, dsr_c, cts_c};
        delayed_modem_signals[3:0] <=  {dcd, ri, dsr, cts};
    end
end
//reg tfifo_empty_ff1,tfifo_empty_ff2;
//always @(posedge clk or negedge rst_n) begin
//   if(!rst_n) begin
//      tfifo_empty_ff1 <=  0;
//      tfifo_empty_ff2 <= 0;
//   end
//   else begin
//      tfifo_empty_ff1 <= tfifo_empty;
//      tfifo_empty_ff2 <= tfifo_empty_ff1;
//   end
//end


// Line Status Register

// activation conditions
assign lsr0 = (rf_count==0 )&& (rx_fifo_wen);  // data in receiver fifo available set condition
assign lsr1 = rf_overrun;     // Receiver overrun error
assign lsr2 = rf_data_out[9]; // parity error bit
assign lsr3 = rf_data_out[8]; // framing error bit
assign lsr4 = rf_data_out[10]; // break error in the character
assign lsr5 = (tfifo_empty && thre_set_en);  // transmitter fifo is empty
//assign lsr5 = (tfifo_empty && thre_set_en);  // transmitter fifo is empty
//assign lsr5 = (!tfifo_full && thre_set_en);  // transmitter fifo is empty
//assign lsr6 = (tfifo_empty && thre_set_en && (tstate == /*S_IDLE */ 0)); // transmitter empty
assign lsr6 = tfifo_empty && thre_set_en ;//&& (tstate == /*S_IDLE */ 0)); // transmitter empty
//assign lsr7 = error | rf_overrun;
assign lsr7 = error_bit || rf_overrun;

// lsr bit0 (receiver data available)
reg      lsr0_d;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr0_d <=  0;
    else lsr0_d <=  lsr0;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr0r <=  0;
    //else lsr0r <= !rfifo_empty;
    else if(rf_count==1 && rfifo_rden && !rx_fifo_wen || rx_reset) lsr0r <=0;
    else if(lsr0 && ~lsr0_d) lsr0r <= 1;
   // else lsr0r <=  (rf_count==1 && rfifo_rden && !rfifo_wen_pulse || rx_reset) ? 0 : // deassert condition
   //                   lsr0r || (lsr0 && ~lsr0_d); // set on rise of lsr0 and keep asserted until deasserted 

// lsr bit 1 (receiver overrun)
reg lsr1_d; // delayed

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr1_d <=  0;
    else lsr1_d <=  lsr1;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr1r <=  0;
    else if(lsr_read_rise) lsr1r <= 0;
    else if(lsr1 && ~lsr1_d) lsr1r <=1;
    //else    lsr1r <=     lsr_read_rise ? 0 : lsr1r || (lsr1 && ~lsr1_d); // set on rise

// lsr bit 2 (parity error)
reg lsr2_d; // delayed

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr2_d <=  0;
    else lsr2_d <=  lsr2;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr2r <=  0;
    else if(lsr_read_rise) lsr2r <= 0;
    else if(lsr2 && ~lsr2_d) lsr2r <= 1;
    //else lsr2r <=  lsr_read_rise ? 0 : lsr2r || (lsr2 && ~lsr2_d); // set on rise

// lsr bit 3 (framing error)
reg lsr3_d; // delayed

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr3_d <=  0;
    else lsr3_d <=  lsr3;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr3r <=  0;
    else if(lsr_read_rise) lsr3r <= 0;
    else if(lsr3 && ~lsr3_d) lsr3r <=1;
    //else lsr3r <=  lsr_read_rise ? 0 : lsr3r || (lsr3 && ~lsr3_d); // set on rise

// lsr bit 4 (break indicator)
reg lsr4_d; // delayed

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr4_d <=  0;
    else lsr4_d <=  lsr4;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr4r <=  0;
    else if(lsr_read_rise) lsr4r <= 0;
    else if(lsr4 && ~lsr4_d) lsr4r <=1;
    //else lsr4r <=  lsr_read_rise ? 0 : lsr4r || (lsr4 && ~lsr4_d);

// lsr bit 5 (transmitter fifo is empty)
//reg lsr5_d;
//
//always @(posedge clk or negedge rst_n)
//    if(!rst_n) lsr5_d <=  1;
//    else lsr5_d <=  lsr5;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr5r <=  1;
    else lsr5r <= tfifo_empty;
    //else if(fifo_write) lsr5r <= 0;
    //else if(lsr5 && ~lsr5_d) lsr5r <=  1;
    //else lsr5r <=  (fifo_write) ? 0 :  lsr5r || (lsr5 && ~lsr5_d);

// lsr bit 6 (transmitter empty indicator)
//reg lsr6_d;
//
//always @(posedge clk or negedge rst_n)
//    if(!rst_n) lsr6_d <=  1;
//    else lsr6_d <=  lsr6;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr6r <=  1;
    else lsr6r <= tfifo_empty;
    //else if(fifo_write) lsr6r <= 0;
    //else if(lsr6 && ~lsr6_d) lsr6r <=  1;
    //else lsr6r <=  (fifo_write) ? 0 : lsr6r || (lsr6 && ~lsr6_d);

// lsr bit 7 (error in fifo)
reg lsr7_d;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr7_d <=  0;
    else lsr7_d <=  lsr7;

always @(posedge clk or negedge rst_n)
    if(!rst_n) lsr7r <=  0;
    else if(lsr_read_rise) lsr7r <= 0;
    else if(lsr7 && ~lsr7_d) lsr7r <=1;
    //else lsr7r <=  lsr_read_rise ? 0 : lsr7r || (lsr7 && ~lsr7_d);

// Frequency divider
reg [7:0] clk_cnt;
wire clk_enable;
assign clk_enable= (clk_cnt == clk_divisor);
always @(posedge uart_clk or negedge uart_rst_n) 
begin
   if(!uart_rst_n) begin
      dlc <=  0;
   end
   //else if(start_dlc) dlc <=  dl - 1;
   else if(clk_enable) begin
        if (dlc==0)
              dlc <=  dl - 1;               // preset counter
        else
            dlc <=  dlc - 1;              // decrement counter
   end
end

// Enable signal generation logic
always @(posedge uart_clk or negedge uart_rst_n)begin
   if(!uart_rst_n) clk_cnt<=0;
   else if(clk_cnt == clk_divisor) begin
      clk_cnt <= 0;
   end
   else begin
      clk_cnt <= clk_cnt +1;
   end
   //else if(start_dlc) clk_cnt <=clk_divisor;
   //else if(clk_cnt == 0) begin
   //   clk_cnt <=clk_divisor;
   //end
   //else if(dl!=0) begin
   //   clk_cnt <= clk_cnt-1;
   //end
   //else if
   //else begin
   //   clk_cnt <=clk_divisor;
   //end
end

always @(posedge uart_clk or negedge uart_rst_n)
begin
    if(!uart_rst_n)
        enable <=  1'b0;
    else begin
        if (dlc==0 && clk_enable)     // dl>0 & dlc==0
            enable <=  1'b1;
        else
            enable <=  1'b0;
   end
end

// Delaying THRE status for one character cycle after a character is written to an empty fifo.
always @(lcr)
  case (lcr[3:0])
    4'b0000                             : block_value =  95; // 6 bits
    4'b0100                             : block_value = 103; // 6.5 bits
    4'b0001, 4'b1000                    : block_value = 111; // 7 bits
    4'b1100                             : block_value = 119; // 7.5 bits
    4'b0010, 4'b0101, 4'b1001           : block_value = 127; // 8 bits
    4'b0011, 4'b0110, 4'b1010, 4'b1101  : block_value = 143; // 9 bits
    4'b0111, 4'b1011, 4'b1110           : block_value = 159; // 10 bits
    4'b1111                             : block_value = 175; // 11 bits
  endcase // case(lcr[3:0])

// Counting time of one character minus stop bit
always @(posedge clk or negedge rst_n)
begin
  if(!rst_n)
    block_cnt <=  8'd0;
  else if(lsr5r & fifo_write)  // THRE bit set & write to fifo occured
    block_cnt <=  block_value;
  else if (enable & block_cnt != 8'b0)  // only work on enable times
    block_cnt <=  block_cnt - 1;  // decrement break counter
end 

// Generating THRE status enable signal
//assign thre_set_en = ~(|block_cnt);
assign thre_set_en = 1'b1;//block_cnt==0;


//
//    INTERRUPT LOGIC
//

assign rls_int  = ier[UART_IE_RLS] && (lsr[UART_LS_OE] || lsr[UART_LS_PE] || lsr[UART_LS_FE] || lsr[UART_LS_BI]);
assign rda_int  = ier[UART_IE_RDA] && (rf_count >= {1'b0,trigger_level});
assign thre_int = ier[UART_IE_THRE] && lsr[UART_LS_TFE];
assign ms_int   = ier[UART_IE_MS] && (| msr[3:0]);
assign ti_int   = ier[UART_IE_RDA] && (counter_t == 10'b0) && (|rf_count);

reg      rls_int_d;
reg      thre_int_d;
reg      ms_int_d;
reg      ti_int_d;
reg      rda_int_d;

// delay lines
always  @(posedge clk or negedge rst_n)
    if(!rst_n) rls_int_d <=  0;
    else rls_int_d <=  rls_int;

always  @(posedge clk or negedge rst_n)
    if(!rst_n) rda_int_d <=  0;
    else rda_int_d <=  rda_int;

always  @(posedge clk or negedge rst_n)
    if(!rst_n) thre_int_d <=  0;
    else thre_int_d <=  thre_int;

always  @(posedge clk or negedge rst_n)
    if(!rst_n) ms_int_d <=  0;
    else ms_int_d <=  ms_int;

always  @(posedge clk or negedge rst_n)
    if(!rst_n) ti_int_d <=  0;
    else ti_int_d <=  ti_int;

// rise detection signals

wire      rls_int_rise;
wire      thre_int_rise;
wire      ms_int_rise;
wire      ti_int_rise;
wire      rda_int_rise;

assign rda_int_rise    = rda_int & ~rda_int_d;
assign rls_int_rise       = rls_int & ~rls_int_d;
assign thre_int_rise   = thre_int & ~thre_int_d;
assign ms_int_rise       = ms_int & ~ms_int_d;
assign ti_int_rise       = ti_int & ~ti_int_d;

// interrupt pending flags
reg     rls_int_pnd;
reg    rda_int_pnd;
reg     thre_int_pnd;
reg     ms_int_pnd;
reg     ti_int_pnd;

// interrupt pending flags assignments
always  @(posedge clk or negedge rst_n)
    if(!rst_n) rls_int_pnd <=  0; 
    else 
        rls_int_pnd <=  lsr_read_rise ? 0 :                          // reset condition
                            rls_int_rise ? 1 :                        // latch condition
                            rls_int_pnd && ier[UART_IE_RLS];    // default operation: remove if masked

always  @(posedge clk or negedge rst_n)
    if(!rst_n) rda_int_pnd <=  0; 
    else 
        rda_int_pnd <=  ((rf_count <= {1'b0,trigger_level}) && fifo_read) ? 0 :      // reset condition
                            rda_int_rise ? 1 :                        // latch condition
                            rda_int_pnd && ier[UART_IE_RDA];    // default operation: remove if masked

always  @(posedge clk or negedge rst_n)
    if(!rst_n) thre_int_pnd <=  0; 
    else 
        thre_int_pnd <=  fifo_write || (iir_read & ~iir[UART_II_IP] & iir[3:1] == UART_II_THRE)? 0 : 
                            thre_int_rise ? 1 :
                            thre_int_pnd && ier[UART_IE_THRE];

always  @(posedge clk or negedge rst_n)
    if(!rst_n) ms_int_pnd <=  0; 
    else 
        ms_int_pnd <=  msr_read ? 0 : 
                            ms_int_rise ? 1 :
                            ms_int_pnd && ier[UART_IE_MS];

always  @(posedge clk or negedge rst_n)
    if(!rst_n) ti_int_pnd <=  0; 
    else 
        ti_int_pnd <=  fifo_read ? 0 : 
                            ti_int_rise ? 1 :
                            ti_int_pnd && ier[UART_IE_RDA];
// end of pending flags

// INT_O logic
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)    
        int_o <=  1'b0;
    else
        int_o <=  
                    rls_int_pnd        ?    ~lsr_read_rise                    :
                    rda_int_pnd        ? 1                                :
                    ti_int_pnd        ? ~fifo_read                    :
                    thre_int_pnd    ? !(fifo_write & iir_read) :
                    ms_int_pnd        ? ~msr_read                        :
                    0;    // if no interrupt are pending
end


// Interrupt Identification register
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        iir <=  1;
    else
    if (rls_int_pnd)  // interrupt is pending
    begin
        iir[3:1] <=  UART_II_RLS;    // set identification register to correct value
        iir[UART_II_IP] <=  1'b0;        // and clear the IIR bit 0 (interrupt pending)
    end else // the sequence of conditions determines priority of interrupt identification
    if (rda_int)
    begin
        iir[3:1] <=  UART_II_RDA;
        iir[UART_II_IP] <=  1'b0;
    end
    else if (ti_int_pnd)
    begin
        iir[3:1] <=  UART_II_TI;
        iir[UART_II_IP] <=  1'b0;
    end
    else if (thre_int_pnd)
    begin
        iir[3:1] <=  UART_II_THRE;
        iir[UART_II_IP] <=  1'b0;
    end
    else if (ms_int_pnd)
    begin
        iir[3:1] <=  UART_II_MS;
        iir[UART_II_IP] <=  1'b0;
    end else    // no interrupt is pending
    begin
        iir[3:1] <=  0;
        iir[UART_II_IP] <=  1'b1;
    end
end

endmodule
